/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: 
 * 系统版本: 1.0.0
 * 开发人员: Frank
 * 开发时间: 2019/12/5 22:22
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.spring.arch.common.db;

import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.datasource.init.ScriptUtils;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.LineNumberReader;
import java.sql.Connection;
import java.util.StringJoiner;

/**
 * 数据库操作工具类
 *
 * @author Frank
 * @version 1.0.0.1
 * @since 2019/12/5 22:22
 */
@Slf4j
@UtilityClass
public class DBUtils {

    /**
     * 获取数据库实例URL
     *
     * @param masterUrl 主库URL
     * @param dbType    数据库类型
     * @return 数据库实例URL
     */
    public static String getInstanceUrl(String masterUrl, String schema, DBType dbType) {
        JdbcUrlSplitter splitter = new JdbcUrlSplitter(masterUrl);
        final String host = splitter.getHost();
        final int port = Integer.parseInt(splitter.getPort());
        final String params = splitter.getParams();
        return dbType.getUrl(host, port, schema, params);
    }

    /**
     * 获取数据库schema
     *
     * @param jdbcUrl
     * @return 数据库实例URL
     */
    public static String getSchema(String jdbcUrl) throws Exception {
        JdbcUrlSplitter splitter = new JdbcUrlSplitter(jdbcUrl);
        return splitter.getDatabase();
    }

    /**
     * 运行sql脚本
     *
     * @param dataSource 数据源
     * @param schema     实例名
     * @param username   用户名
     * @param password   密码
     */
    public static void runSqlScripts(DBCommand command, DataSource dataSource, String schema, String username, String password) throws Exception {
        username = StringUtils.isBlank(username) ? schema : username;
        password = StringUtils.isBlank(password) ? schema : password;
        String scriptName = new StringJoiner(command.name().toLowerCase())
                .add("datasource-").add(".sql").toString();
        ClassPathResource rc = new ClassPathResource(scriptName);
        EncodedResource er = new EncodedResource(rc, "utf-8");
        String sqlFileContent = readScript(er);
        String sqlContent = sqlFileContent
                .replace("$schema", schema)
                .replace("$username", username)
                .replace("$password", password);
        log.info("\n\n>>>>>>>>>>执行脚本文件-{}：【\n\t{}\n】\n", scriptName, StringUtils.replace(sqlContent, "\n", "\n\t"));
        er = new EncodedResource(new ByteArrayResource(sqlContent.getBytes()));
        final Connection connection = DataSourceUtils.getConnection(dataSource);
        ScriptUtils.executeSqlScript(connection, er);
    }

    private static String getSqlFileContent(EncodedResource resource) throws IOException {
        try (LineNumberReader lnr = new LineNumberReader(resource.getReader())) {
            return ScriptUtils.readScript(lnr, ScriptUtils.DEFAULT_COMMENT_PREFIX, ScriptUtils.DEFAULT_STATEMENT_SEPARATOR, ScriptUtils.DEFAULT_BLOCK_COMMENT_END_DELIMITER);
        }
    }

    private static String readScript(EncodedResource resource) throws IOException {
        return getSqlFileContent(resource);
    }
}
